#ifndef     __MESSAGE_QUEUE_H
#define     __MESSAGE_QUEUE_H

#include "./rtos.h"
#include "../utils/assert.h"
#include "../utils/no_copyable.h"

namespace rtos {

template <typename MsgType, uint32_t MsgLimit>
class MessageQueue : private utils::no_copyable_t {
    constexpr static uint32_t MqSize = osRtxMessageQueueMemSize(MsgLimit, sizeof (MsgType));
public:
    MessageQueue(const char *name = "other") {
        osMessageQueueAttr_t attr;
        attr.name = name;
        attr.attr_bits = 0;
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxMessageQueueCbSize;
        attr.mq_mem = m_mq_mem;
        attr.mq_size = MqSize;
        m_id = osMessageQueueNew(MsgLimit, sizeof (MsgType), &attr);
        utils::assert(m_id != NULL);
    }

    inline osStatus_t post(const MsgType &msg) {
        return osMessageQueuePut(m_id, &msg, 0, 0);
    }

    inline osStatus_t poll(MsgType& msg, uint32_t timeout = osWaitForever) {
        return osMessageQueueGet(m_id, &msg, NULL, timeout);
    }

    inline osStatus_t reset() {
        return osMessageQueueReset(m_id);
    }

    inline MsgType take() {
        MsgType msg;
        poll(msg);
        return msg;
    }

private:
    osMessageQueueId_t m_id;
    uint64_t m_cb_mem[(osRtxMessageQueueCbSize + 7) / 8];
    uint64_t m_mq_mem[(MqSize + 7) / 8];
};

}


#endif
